package com.zxb.base.auth.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zxb.base.auth.service.AuthOrgService;
import com.zxb.core.dao.auth.AuthOrg;
import com.zxb.core.dao.auth.AuthOrgDao;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Zxb
 */
@Service
@RequiredArgsConstructor
public class AuthOrgServiceImpl implements AuthOrgService {
    private final AuthOrgDao orgDao;

    @Override
    public String generateNewName(Long pid) {
        String defaultName = "新增节点";
        String newName = defaultName;
        Integer i = 1;
        while (
                orgDao.exists(new LambdaQueryWrapper<AuthOrg>()
                        .eq(AuthOrg::getPid, pid)
                        .eq(AuthOrg::getName, newName))
        ) {
            newName = defaultName + i;
            i += 1;
        }
        return newName;
    }

    @Override
    public Boolean isNameConflict(Long id, String name) {
        AuthOrg obj = orgDao.getById(id);
        return orgDao.exists(new LambdaQueryWrapper<AuthOrg>()
                .eq(AuthOrg::getPid, obj.getPid())
                .eq(AuthOrg::getName, name)
                .ne(AuthOrg::getId, id));
    }

    @Override
    public Boolean isCodeConflict(Long id, String code) {
        AuthOrg obj = orgDao.getById(id);
        return orgDao.exists(new LambdaQueryWrapper<AuthOrg>()
                .eq(AuthOrg::getPid, obj.getPid())
                .eq(AuthOrg::getCode, code)
                .ne(AuthOrg::getId, id));
    }

    @Override
    public Integer findMaxSort(Long pid) {
        List<AuthOrg> list = orgDao.list(new LambdaQueryWrapper<AuthOrg>()
                .eq(AuthOrg::getPid, pid)
                .orderByDesc(AuthOrg::getSort));
        return CollUtil.isEmpty(list) ? 0 : list.get(0).getSort();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void moveInner(AuthOrg dragObj, AuthOrg dropObj) {
        Long pid = dropObj.getId();
        if (!dragObj.getPid().equals(pid)) {
            //之前不是子节点
            dragObj.setPid(pid);
            dragObj.setLayer(dropObj.getLayer() + 1);
        }
        //放到所有子节点的后面
        dragObj.setSort(findMaxSort(dropObj.getId()) + 1);
        orgDao.updateById(dragObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void moveBefore(AuthOrg dragObj, AuthOrg dropObj) {
        Long pid = dropObj.getPid();
        Integer sort = dropObj.getSort();

        List<AuthOrg> orgList = orgDao.list(
                new LambdaQueryWrapper<AuthOrg>()
                        .eq(AuthOrg::getPid, pid)
                        .ge(AuthOrg::getSort, sort)
                        .ne(AuthOrg::getId, dragObj.getId())
        );
        orgList.stream().forEach(t -> {
            t.setSort(t.getSort() + 1);
        });
        orgDao.updateBatchById(orgList);

        AuthOrg parent = orgDao.getById(pid);
        dragObj.setPid(pid);
        dragObj.setLayer(parent.getLayer() + 1);
        dragObj.setSort(sort);
        orgDao.updateById(dragObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void moveAfter(AuthOrg dragObj, AuthOrg dropObj) {
        Long pid = dropObj.getPid();
        Integer sort = dropObj.getSort();

        List<AuthOrg> orgList = orgDao.list(
                new LambdaQueryWrapper<AuthOrg>()
                        .eq(AuthOrg::getPid, pid)
                        .gt(AuthOrg::getSort, sort)
                        .ne(AuthOrg::getId, dragObj.getId())
        );
        orgList.stream().forEach(t -> {
            t.setSort(t.getSort() + 1);
        });
        orgDao.updateBatchById(orgList);

        AuthOrg parent = orgDao.getById(pid);
        dragObj.setPid(pid);
        dragObj.setLayer(parent.getLayer() + 1);
        dragObj.setSort(sort + 1);
        orgDao.updateById(dragObj);
    }

    @Override
    public void generateLink(AuthOrg org) {
        Long id = org.getId();
        List<String> nameList = new ArrayList<>();
        List<Long> idList = new ArrayList<>();
        while (org != null) {
            nameList.add(org.getName());
            idList.add(org.getId());
            if (org.getPid() == null) {
                org = null;
            } else {
                org = orgDao.getById(org.getPid());
            }
        }

        Collections.reverse(nameList);
        Collections.reverse(idList);

        String resultStr = "";
        for (String str : nameList) {
            resultStr += str + "/";
        }

        resultStr = resultStr.substring(0, resultStr.length() - 1);

        AuthOrg old = orgDao.getById(id);
        old.setNameLink(resultStr);
        old.setIdLink(idList.stream().map(t -> String.valueOf(t)).collect(Collectors.joining(",")));
        orgDao.updateById(old);
    }
}
